home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Games / DroneZone / DZGame.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  17.1 KB  |  678 lines  |  [TEXT/MPS ]

  1. /*
  2.  *    File:        DZGame.c
  3.  *
  4.  *    Contents:    Handles the game play.
  5.  *
  6.  *    Copyright © 1996 Apple Computer, Inc.
  7.  */
  8.  
  9. #include <assert.h>
  10. #include <string.h>
  11.  
  12. #include <Events.h>
  13. #include <Fonts.h>
  14. #include <QDOffscreen.h>
  15. #include <Timer.h>
  16. #include <Types.h>
  17.  
  18. #include <QD3D.h>
  19. #include <QD3DGeometry.h>
  20. #include <QD3DMath.h>
  21. #include <QD3DSet.h>
  22.  
  23. #include "SoundSprocket.h"
  24.  
  25. #include "DZDisplay.h"
  26. #include "DZDrone.h"
  27. #include "DZGame.h"
  28. #include "DZInput.h"
  29. #include "DZSound.h"
  30. #include "DZSpace.h"
  31.  
  32. #ifndef ONE_DRONE
  33.     #define ONE_DRONE        0
  34. #endif
  35.  
  36. #ifndef    HUD_SHOWS_VELOCITY_VECTOR
  37. #define    HUD_SHOWS_VELOCITY_VECTOR    1
  38. #endif
  39.  
  40.  
  41. #define DEFAULT_INTERVAL    0.05        // Initial frame rate -- just a guess
  42. #define MAX_INTERVAL        0.25        // Limit on seconds per frame
  43.  
  44. #define INV_SQRT_TWO        0.707
  45.  
  46. #define ROLL_RATE                    3.0            // Radians per second for full joystick throw
  47. #define PITCH_RATE                    1.0            // Radians per second for full joystick throw
  48. #define YAW_RATE                    3.0            // Radians per second for full joystick throw
  49. #define ENGINE_RATING                1.0            // Percentage engine is more/less powerful
  50. #define DAMPING_PERCENT                0.90         // as a percentage (1.00 would be no damping)
  51.  
  52. #define TICKS_PER_AUTOFIRE_SHOT        60             // numbers of ticks until next auto-repeat shot
  53.  
  54. enum {
  55.     #if ONE_DRONE
  56.         kGameAutoDroneCount = 1            // Number of autopilot drones
  57.     #else
  58.         kGameAutoDroneCount = 4            // Number of autopilot drones
  59.     #endif
  60. };
  61.  
  62.  
  63. float                        gGameInterval            = DEFAULT_INTERVAL;
  64. float                        gGameFramesPerSecond    = 1.0/DEFAULT_INTERVAL;
  65.  
  66. Boolean                        gSoundOn                = true;
  67.  
  68.  
  69. static TGameState            gGameState                = kGameState_Stopped;
  70.  
  71. static unsigned long        gGameTime                = 0;        // Last frame time
  72.  
  73. static Boolean                gGameHUDVisible            = true;
  74.  
  75. static TDroneObject            gGameSelfDrone            = NULL;
  76.  
  77. static GWorldPtr            gGameFPSGWorld            = NULL;
  78. static TQ3GeometryObject    gGameFPSMarker            = NULL;
  79. static TQ3MarkerData        gGameFPSMarkerData;
  80. static Boolean                gGameFPSVisible            = false;
  81.  
  82. static GWorldPtr            gGameThrottleGWorld            = NULL;
  83. static TQ3GeometryObject    gGameThrottleMarker            = NULL;
  84. static TQ3MarkerData        gGameThrottleMarkerData;
  85. static Boolean                gGameThrottleVisible    = false;
  86.  
  87. static GWorldPtr            gGameVelocityGWorld            = NULL;
  88. static TQ3GeometryObject    gGameVelocityMarker            = NULL;
  89. static TQ3MarkerData        gGameVelocityMarkerData;
  90. static Boolean                gGameVelocityVisible    = true;
  91.  
  92. static Boolean                gInertialDampersOn        = false;
  93. static Boolean                gFiringOn                = false;
  94. static UInt32                gLastShotTicks            = 0;
  95.  
  96. static TQ3GeometryObject    gGameCrossHairs            = NULL;
  97. static unsigned long        gGameCrossHairsData[32]    = {
  98.     0x00000000, 0x00000000, 0x00000000, 0x00000000,
  99.     0x00000000, 0x00010000, 0x00000000, 0x00010000,
  100.     0x00000000, 0x00054000, 0x00101000, 0x00228800,
  101.     0x00082000, 0x00400400, 0x00101000, 0x05400540,
  102.     0x00101000, 0x00400400, 0x00082000, 0x00228800,
  103.     0x00101000, 0x00054000, 0x00000000, 0x00010000,
  104.     0x00000000, 0x00010000, 0x00000000, 0x00000000,
  105.     0x00000000, 0x00000000, 0x00000000, 0x00000000
  106. };
  107.  
  108.  
  109. /* =============================================================================
  110.  *        Game_Init (external)
  111.  *
  112.  *    Initializes the game stuff.
  113.  * ========================================================================== */
  114. void Game_Init(
  115.     void)
  116. {
  117.     Rect                bounds;
  118.     PixMapHandle        pixMapHandle;
  119.     CGrafPtr            savePort;
  120.     GDHandle            saveGDevice;
  121.     TQ3MarkerData        markerData;
  122.     TQ3ColorRGB            color;
  123.     
  124.     // Set up the 3D sound listener
  125.     Sound_GetListener();
  126.     
  127.     // Create the FPS marker
  128.     bounds.top    = 0;
  129.     bounds.left   = 0;
  130.     bounds.bottom = 12;
  131.     bounds.right  = 31;
  132.     
  133.     gGameFPSGWorld = NULL;
  134.     NewGWorld(&gGameFPSGWorld, 1, &bounds, NULL, NULL, 0);
  135.     assert(gGameFPSGWorld != NULL);
  136.     
  137.     LockPixels(gGameFPSGWorld->portPixMap);
  138.     
  139.     GetGWorld(&savePort, &saveGDevice);
  140.     SetGWorld(gGameFPSGWorld, NULL);
  141.     
  142.     TextFont(kFontIDGeneva);
  143.     TextSize(10);
  144.     
  145.     EraseRect(&gGameFPSGWorld->portRect);
  146.     
  147.     SetGWorld(savePort, saveGDevice);
  148.     
  149.     pixMapHandle = GetGWorldPixMap(gGameFPSGWorld);
  150.     
  151.     gGameFPSMarkerData.location.x            = 0.0;
  152.     gGameFPSMarkerData.location.y            = 0.0;
  153.     gGameFPSMarkerData.location.z            = 0.0;
  154.     gGameFPSMarkerData.xOffset                = -(bounds.left+bounds.right+1 >> 1);
  155.     gGameFPSMarkerData.yOffset                = -(bounds.top+bounds.bottom+1 >> 1);
  156.     gGameFPSMarkerData.bitmap.image            = (unsigned char*) GetPixBaseAddr(pixMapHandle);
  157.     gGameFPSMarkerData.bitmap.width            = bounds.right-bounds.left;
  158.     gGameFPSMarkerData.bitmap.height        = bounds.bottom-bounds.top;
  159.     gGameFPSMarkerData.bitmap.rowBytes        = (*pixMapHandle)->rowBytes & 0x00003FFF;
  160.     gGameFPSMarkerData.bitmap.bitOrder        = kQ3EndianBig;
  161.     gGameFPSMarkerData.markerAttributeSet    = Q3AttributeSet_New();
  162.     assert(gGameFPSMarkerData.markerAttributeSet != NULL);
  163.     
  164.     color.r = 1.0;
  165.     color.g = 1.0;
  166.     color.b = 0.4;
  167.     
  168.     Q3AttributeSet_Add(gGameFPSMarkerData.markerAttributeSet, kQ3AttributeTypeDiffuseColor, &color);
  169.     
  170.     gGameFPSMarker = Q3Marker_New(&gGameFPSMarkerData);
  171.  
  172.     // Create the Velocity marker
  173.     bounds.top    = 0;
  174.     bounds.left   = 0;
  175.     bounds.bottom = 12;
  176.     bounds.right  = 31;
  177.     
  178.     gGameVelocityGWorld = NULL;
  179.     NewGWorld(&gGameVelocityGWorld, 1, &bounds, NULL, NULL, 0);
  180.     assert(gGameVelocityGWorld != NULL);
  181.     
  182.     LockPixels(gGameVelocityGWorld->portPixMap);
  183.     
  184.     GetGWorld(&savePort, &saveGDevice);
  185.     SetGWorld(gGameVelocityGWorld, NULL);
  186.     
  187.     TextFont(kFontIDGeneva);
  188.     TextSize(10);
  189.     
  190.     EraseRect(&gGameVelocityGWorld->portRect);
  191.     
  192.     SetGWorld(savePort, saveGDevice);
  193.     
  194.     pixMapHandle = GetGWorldPixMap(gGameVelocityGWorld);
  195.     
  196.     gGameVelocityMarkerData.location.x            = 0.0;
  197.     gGameVelocityMarkerData.location.y            = 0.0;
  198.     gGameVelocityMarkerData.location.z            = 0.0;
  199.     gGameVelocityMarkerData.xOffset                = -(bounds.left+bounds.right+1 >> 1);
  200.     gGameVelocityMarkerData.yOffset                = -(bounds.top+bounds.bottom+1 >> 1);
  201.     gGameVelocityMarkerData.bitmap.image        = (unsigned char*) GetPixBaseAddr(pixMapHandle);
  202.     gGameVelocityMarkerData.bitmap.width        = bounds.right-bounds.left;
  203.     gGameVelocityMarkerData.bitmap.height        = bounds.bottom-bounds.top;
  204.     gGameVelocityMarkerData.bitmap.rowBytes        = (*pixMapHandle)->rowBytes & 0x00003FFF;
  205.     gGameVelocityMarkerData.bitmap.bitOrder        = kQ3EndianBig;
  206.     gGameVelocityMarkerData.markerAttributeSet    = Q3AttributeSet_New();
  207.     assert(gGameVelocityMarkerData.markerAttributeSet != NULL);
  208.     
  209.     color.r = 1.0;
  210.     color.g = 1.0;
  211.     color.b = 0.4;
  212.     
  213.     Q3AttributeSet_Add(gGameVelocityMarkerData.markerAttributeSet, kQ3AttributeTypeDiffuseColor, &color);
  214.     
  215.     gGameVelocityMarker = Q3Marker_New(&gGameVelocityMarkerData);
  216.     
  217.     // Create the crosshairs
  218.     markerData.location.x            = 0.0;
  219.     markerData.location.y            = 0.0;
  220.     markerData.location.z            = 0.0;
  221.     markerData.xOffset                = -15;
  222.     markerData.yOffset                = -15;
  223.     markerData.bitmap.image            = (unsigned char*) gGameCrossHairsData;
  224.     markerData.bitmap.width            = 31;  //• SHOULD BE 32, BUT TO GET AROUND A APPLE QD3D ACCEL CARD DRIVER BUG...
  225.     markerData.bitmap.height        = 32;
  226.     markerData.bitmap.rowBytes        = 4;
  227.     markerData.bitmap.bitOrder        = kQ3EndianBig;
  228.     markerData.markerAttributeSet    = Q3AttributeSet_New();
  229.     assert(markerData.markerAttributeSet != NULL);
  230.     
  231.     color.r = 1.0;
  232.     color.g = 1.0;
  233.     color.b = 0.4;
  234.     
  235.     Q3AttributeSet_Add(markerData.markerAttributeSet, kQ3AttributeTypeDiffuseColor, &color);
  236.     
  237.     gGameCrossHairs = Q3Marker_New(&markerData);
  238.     
  239.     Q3Object_Dispose(markerData.markerAttributeSet);
  240.     markerData.markerAttributeSet = NULL;
  241. }
  242.  
  243.  
  244. /* =============================================================================
  245.  *        Game_Exit (external)
  246.  *
  247.  *    Prepares for exit.
  248.  * ========================================================================== */
  249. void Game_Exit(
  250.     void)
  251. {
  252.     if (gGameFPSMarker != NULL)
  253.     {
  254.         Q3Object_Dispose(gGameFPSMarker);
  255.         gGameFPSMarker = NULL;
  256.     }
  257.     
  258.     if (gGameVelocityMarker != NULL)
  259.     {
  260.         Q3Object_Dispose(gGameVelocityMarker);
  261.         gGameVelocityMarker = NULL;
  262.     }
  263.     
  264.     if (gGameCrossHairs != NULL)
  265.     {
  266.         Q3Object_Dispose(gGameCrossHairs);
  267.         gGameCrossHairs = NULL;
  268.     }
  269. }
  270.  
  271.  
  272. /* =============================================================================
  273.  *        Game_GetState (external)
  274.  *
  275.  *    Returns the game state.
  276.  * ========================================================================== */
  277. TGameState Game_GetState(
  278.     void)
  279. {
  280.     return gGameState;
  281. }
  282.  
  283.  
  284. /* =============================================================================
  285.  *        Game_SetState (external)
  286.  *
  287.  *    Changes the game state.
  288.  * ========================================================================== */
  289. void Game_SetState(
  290.     TGameState            inGameState)
  291. {
  292.     TGameState            prevGameState;
  293.     TDroneObject        drone;
  294.     int                    droneNum;
  295.     
  296.     if (gGameState != inGameState)
  297.     {
  298.         prevGameState = gGameState;
  299.         gGameState = inGameState;
  300.         
  301.         switch (gGameState)
  302.         {
  303.             case kGameState_Playing:
  304.                 // Begin Playing
  305.                 if (prevGameState == kGameState_Stopped)
  306.                 {
  307.                     gGameSelfDrone = SelfDrone_New();
  308.                     
  309.                     // Create some automatic drones
  310.                     for (droneNum = 0; droneNum < kGameAutoDroneCount; droneNum++)
  311.                     {
  312.                         AutoDrone_New(gGameSelfDrone);
  313.                     }
  314.                 }
  315.                 
  316.                 Display_DrawContents();
  317.                 Input_Activate(true);
  318.             break;
  319.             
  320.             case kGameState_Paused:
  321.                 // From Playing to Paused
  322.                 assert(prevGameState != kGameState_Stopped);
  323.                 
  324.                 Game_Silence();
  325.                 Display_DrawContents();
  326.                 Input_Activate(false);
  327.             break;
  328.             
  329.             case kGameState_Stopped:
  330.                 // From Playing or Paused to Stopped
  331.                 while ((drone = Drone_Next(NULL)) != NULL)
  332.                 {
  333.                     Drone_Dispose(drone);
  334.                 }
  335.                 
  336.                 gGameSelfDrone = NULL;
  337.                 
  338.                 Display_DrawContents();
  339.                 Input_Activate(false);
  340.             break;
  341.         }
  342.     }
  343. }
  344.  
  345.  
  346. /* =============================================================================
  347.  *        Game_Process (external)
  348.  *
  349.  *    Handles idle time by moving the game ahead one time step.  Only called if
  350.  *    the game is in "play" state.
  351.  * ========================================================================== */
  352. void Game_Process(
  353.     void)
  354. {
  355.     UnsignedWide        wide;
  356.     unsigned long        now;
  357.     Str15                str;
  358.     CGrafPtr            savePort;
  359.     GDHandle            saveGDevice;
  360.     TDroneObject        drone;
  361.     TDroneObject        next;
  362.     TQ3Point3D            position;
  363.     TQ3Vector3D            direction;
  364.     TQ3Vector3D            up;
  365.     TQ3Matrix4x4        matrix;
  366.     Boolean                ok;
  367.     UInt32                count;
  368.     
  369.     // Find the frame rate
  370.     Microseconds(&wide);
  371.     now = wide.lo;
  372.     
  373.     if (gGameTime != 0)
  374.     {
  375.         // Find the interval for the last frame
  376.         gGameInterval = 0.000001*(now-gGameTime);
  377.         
  378.         // Limit frame rate to a resonable number
  379.         if (gGameInterval > MAX_INTERVAL)
  380.         {
  381.             gGameInterval = MAX_INTERVAL;
  382.         }
  383.         
  384.         // Find corresponding frames per second
  385.         gGameFramesPerSecond = 1.0/gGameInterval;
  386.     }
  387.     
  388.     gGameTime = now;
  389.     
  390.     // Update the FPS marker
  391.     if (gGameFPSVisible)
  392.     {
  393.         sprintf((char*) str, "x%.1f", gGameFramesPerSecond);
  394.         str[0] = strlen((char*) str) - 1;
  395.         
  396.         GetGWorld(&savePort, &saveGDevice);
  397.         SetGWorld(gGameFPSGWorld, NULL);
  398.         
  399.         EraseRect(&gGameFPSGWorld->portRect);
  400.         
  401.         MoveTo(gGameFPSGWorld->portRect.left+gGameFPSGWorld->portRect.right-StringWidth(str) >> 1, 10);
  402.         DrawString(str);
  403.         
  404.         SetGWorld(savePort, saveGDevice);
  405.         
  406.         Q3Marker_SetBitmap(gGameFPSMarker, &gGameFPSMarkerData.bitmap);
  407.     }
  408.  
  409.     // Update the velocity marker
  410.     if (gGameVelocityVisible)
  411.     {
  412.         TQ3Vector3D        velocity;
  413.         
  414.         Drone_GetVelocity(gGameSelfDrone, &velocity);
  415.         
  416.         sprintf((char*) str, "x%.1f", gGameFramesPerSecond);
  417.         str[0] = strlen((char*) str) - 1;
  418.         
  419.         GetGWorld(&savePort, &saveGDevice);
  420.         SetGWorld(gGameVelocityGWorld, NULL);
  421.         
  422.         EraseRect(&gGameVelocityGWorld->portRect);
  423.         
  424.         MoveTo(gGameVelocityGWorld->portRect.left+gGameVelocityGWorld->portRect.right-StringWidth(str) >> 1, 10);
  425.         DrawString(str);
  426.         
  427.         SetGWorld(savePort, saveGDevice);
  428.         
  429.         Q3Marker_SetBitmap(gGameVelocityMarker, &gGameVelocityMarkerData.bitmap);
  430.     }
  431.     
  432.     // Get and process state-based inputs
  433.     SelfDrone_Roll(gGameSelfDrone, Input_GetRoll()*gGameInterval*ROLL_RATE);
  434.     SelfDrone_Pitch(gGameSelfDrone, Input_GetPitch()*gGameInterval*PITCH_RATE);
  435.     SelfDrone_Yaw(gGameSelfDrone, Input_GetYaw()*gGameInterval*YAW_RATE);
  436.     
  437.     if (gInertialDampersOn) SelfDrone_DampVelocity(gGameSelfDrone, DAMPING_PERCENT);
  438.  
  439.     SelfDrone_Thrust(gGameSelfDrone, Input_GetThrottle()*gGameInterval*ENGINE_RATING);
  440.  
  441.     if (gFiringOn) 
  442.     {
  443.         UInt32    ticks = TickCount();
  444.         
  445.         if (gLastShotTicks + TICKS_PER_AUTOFIRE_SHOT < ticks)
  446.         {
  447.             Drone_Fire(gGameSelfDrone);
  448.             gLastShotTicks = ticks;
  449.         }
  450.     }
  451.  
  452.     // Get and process input events
  453.     ok = true;
  454.     do
  455.     {
  456.         switch (Input_GetEvent())
  457.         {
  458.             case kInputEvent_None:
  459.                 // No more input events to process
  460.                 ok = false;
  461.             break;
  462.             
  463.             case kInputEvent_Fire_On:
  464.                 // Fire button pressed down
  465.                 Drone_Fire(gGameSelfDrone);
  466.                 gLastShotTicks = TickCount();
  467.                 gFiringOn = true;
  468.             break;
  469.             
  470.             case kInputEvent_Fire_Off:
  471.                 // Fire button released
  472.                 gFiringOn = false;
  473.             break;
  474.             
  475.             case kInputEvent_InertialDampers_On:
  476.                 // Inertial Dampers button down
  477.                 SelfDrone_DampVelocity(gGameSelfDrone, DAMPING_PERCENT);
  478.                 gInertialDampersOn = true;
  479.             break;
  480.             
  481.             case kInputEvent_InertialDampers_Off:
  482.                 // Inertial Dampers button released
  483.                 gInertialDampersOn = false;
  484.             break;
  485.             
  486.             case kInputEvent_InstantStop:
  487.                 // Set Velocity to zero
  488.                 SelfDrone_InstantStop(gGameSelfDrone);
  489.             break;
  490.             
  491.             case kInputEvent_ShowHUD:
  492.                 // Toggle HMD display
  493.                 gGameHUDVisible = !gGameHUDVisible;
  494.             break;
  495.             
  496.             case kInputEvent_ShowFPS:
  497.                 // Toggle FPS display
  498.                 gGameFPSVisible = !gGameFPSVisible;
  499.             break;
  500.             
  501.             case kInputEvent_ShowThrottle:
  502.                 // Toggle throttle display
  503.                 gGameThrottleVisible = !gGameThrottleVisible;
  504.             break;
  505.  
  506.             case kInputEvent_ShowVelocity:
  507.                 // Toggle velocity display
  508.                 gGameVelocityVisible = !gGameVelocityVisible;
  509.             break;
  510.  
  511.             case kInputEvent_Pause:
  512.                 // Toggle paused/play state
  513.                 switch (gGameState)
  514.                 {
  515.                     case kGameState_Playing:
  516.                         Game_SetState(kGameState_Paused);
  517.                     break;
  518.                     
  519.                     case kGameState_Paused:
  520.                         Game_SetState(kGameState_Playing);
  521.                     break;
  522.                     
  523.                     case kGameState_Stopped:
  524.                         // do nothing
  525.                     break;
  526.                 }
  527.             break;
  528.             
  529.         }
  530.     }
  531.     while (ok);
  532.     
  533.     // Move all the drones, mark any to be deleted
  534.     for (drone = Drone_Next(NULL); drone != NULL; drone = Drone_Next(drone))
  535.     {
  536.         Drone_Move(drone);
  537.     }
  538.     
  539.     // Delete the marked drones
  540.     drone = Drone_Next(NULL);
  541.     while (drone != NULL)
  542.     {
  543.         next = Drone_Next(drone);
  544.         
  545.         if (Drone_GetMark(drone))
  546.         {
  547.             Drone_Dispose(drone);
  548.         }
  549.         
  550.         drone = next;
  551.     }
  552.     
  553.     // Move the viewer to follow the self drone
  554.     Drone_GetPosition(gGameSelfDrone, &position);
  555.     Drone_GetDirection(gGameSelfDrone, &direction);
  556.     Drone_GetUp(gGameSelfDrone, &up);
  557.     
  558.     Display_SetViewerPosition(&position, &direction, &up);
  559.     
  560.     if (gSoundOn)
  561.     {
  562.         // Move the listener to follow the self drone
  563.         Drone_GetMatrix(gGameSelfDrone, &matrix);
  564.             SSpListener_SetTransform(Sound_GetListener(), &matrix);
  565.         
  566.         // Change the localized sounds
  567.         for (drone = Drone_Next(NULL); drone != NULL; drone = Drone_Next(drone))
  568.         {
  569.             Drone_UpdateSound(drone);
  570.         }
  571.     }
  572.     
  573.     // Time to retire?
  574.     
  575.     // NOTE: This is not the best way to determine if the game is done.  We
  576.     // should probably ask each drone if it thinks the game should continue.
  577.     // Only AutoDrones would respond yes.  Then we'd "or" the results.
  578.     
  579.     count = 0;
  580.     for (drone = Drone_Next(NULL); drone != NULL; drone = Drone_Next(drone))
  581.     {
  582.         count += 1;
  583.     }
  584.     
  585.     if (count == 1)
  586.     {
  587.         // Only the autodrone is left -- time to quit
  588.         Game_SetState(kGameState_Stopped);
  589.     }
  590. }
  591.  
  592.  
  593. /* =============================================================================
  594.  *        Game_Submit (external)
  595.  *
  596.  *    Submits all the 3D geometry of the game.
  597.  * ========================================================================== */
  598. void Game_Submit(
  599.     TQ3ViewObject        inView)
  600. {
  601.     TDroneObject        drone;
  602.     TQ3Point3D            position;
  603.     TQ3Vector3D            direction;
  604.     TQ3Vector3D            velocity;
  605.     TQ3Vector3D            up;
  606.     TQ3Vector3D            v;
  607.     TQ3Point3D            markerPosition;
  608.     
  609.     assert(inView != NULL);
  610.     
  611.     // Submit the drones
  612.     for (drone = Drone_Next(NULL); drone != NULL; drone = Drone_Next(drone))
  613.     {
  614.         Drone_Submit(drone, gGameHUDVisible, inView);
  615.     }
  616.     
  617.     // Get information about the camera position
  618.     Drone_GetPosition(gGameSelfDrone, &position);
  619.     Drone_GetDirection(gGameSelfDrone, &direction);
  620.     Drone_GetUp(gGameSelfDrone, &up);
  621.     Drone_GetVelocity(gGameSelfDrone, &velocity);
  622.     
  623.     // Submit the spacejunk
  624.     Space_Submit(inView, &position, &direction);
  625.     
  626.     // Submit the FPS marker
  627.     if (gGameFPSVisible)
  628.     {
  629.         Q3Point3D_Vector3D_Add(&position, &direction, &markerPosition);
  630.         Q3Vector3D_Scale(&up, -0.6, &v);
  631.         Q3Point3D_Vector3D_Add(&markerPosition, &v, &markerPosition);
  632.         Q3Marker_SetPosition(gGameFPSMarker, &markerPosition);
  633.         Q3Object_Submit(gGameFPSMarker, inView);
  634.     }
  635.  
  636.     // Submit the velocity marker
  637.     if (gGameVelocityVisible)
  638.     {
  639.         Q3Point3D_Vector3D_Add(&position, &direction, &markerPosition);
  640.         Q3Vector3D_Scale(&up, -0.8, &v);
  641.         Q3Point3D_Vector3D_Add(&markerPosition, &v, &markerPosition);
  642.         Q3Marker_SetPosition(gGameVelocityMarker, &markerPosition);
  643.         Q3Object_Submit(gGameVelocityMarker, inView);
  644.     }
  645.     
  646.     // Submit the crosshairs
  647.     if (gGameHUDVisible)
  648.     {
  649. #if HUD_SHOWS_VELOCITY_VECTOR
  650.         Q3Vector3D_Normalize(&velocity, &velocity);
  651.         Q3Point3D_Vector3D_Add(&position, &velocity, &markerPosition);
  652. #else        
  653.         Q3Point3D_Vector3D_Add(&position, &direction, &markerPosition);
  654. #endif
  655.         Q3Marker_SetPosition(gGameCrossHairs, &markerPosition);
  656.         Q3Object_Submit(gGameCrossHairs, inView);
  657.     }
  658. }
  659.  
  660.  
  661. /* =============================================================================
  662.  *        Game_Silence (external)
  663.  *
  664.  *    Stops all sounds.
  665.  * ========================================================================== */
  666. void Game_Silence(
  667.     void)
  668. {
  669.     TDroneObject        drone;
  670.     
  671.     for (drone = Drone_Next(NULL); drone != NULL; drone = Drone_Next(drone))
  672.     {
  673.         Drone_Silence(drone);
  674.     }
  675. }
  676.  
  677.  
  678.